package org.fast.develop.logicflow.builder;

import org.fast.develop.logicflow.core.meta.shape.LogicFlowDefinition;
import org.fast.develop.logicflow.core.meta.base.Resource;
import org.fast.develop.logicflow.core.meta.shape.line.SequenceFlow;
import org.fast.develop.logicflow.core.LogicFlowConfiguration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 莫寅
 * @createTime 2022-11-25 15:43
 * @desc：
 */
public abstract class AbstractLogicFlowBuilder<T extends AbstractLogicFlowBuilder<T, E>, E extends Resource> {

    private String id;

    private String name;

    private LogicFlowDefinition logicFlowDefinition;

    private E element;

    private LogicFlowConfiguration logicFlowConfiguration;

    private List<AbstractLogicFlowBuilder> incoming = new ArrayList<>();

    private List<AbstractLogicFlowBuilder> outgoing = new ArrayList<>();

    private AbstractLogicFlowBuilder prevAbstractLogicFlowBuilder;

    private AbstractLogicFlowBuilder currentAbstractLogicFlowBuilder;

    private AbstractLogicFlowBuilder sequenceFlowAbstractLogicFlowBuilder;

    private Map<String, SequenceFlow> sequenceFlowElements = new HashMap<>();

    private IfElseControlBuilder currentGatewayAbstractLogicFlowBuilder;

    private LogicFlowBuilderFactory logicFlowBuilderFactory;

    public AbstractLogicFlowBuilder(LogicFlowDefinition logicFlowDefinition, LogicFlowConfiguration logicFlowConfiguration) {
        super();
        this.logicFlowDefinition = logicFlowDefinition;
        this.logicFlowConfiguration = logicFlowConfiguration;
        this.logicFlowBuilderFactory = logicFlowConfiguration.getLogicFlowBuilderFactory();
    }

    public T addIncoming(AbstractLogicFlowBuilder abstractLogicFlowBuilder){
        incoming.add(abstractLogicFlowBuilder);
        return (T) this;
    }

    public T addOutgoing(AbstractLogicFlowBuilder abstractLogicFlowBuilder){
        outgoing.add(abstractLogicFlowBuilder);
        return (T) this;
    }

    public StartEventBuilder startEvent(){
        return startEvent(null);
    }

    public StartEventBuilder startEvent(String id) {
        return logicFlowBuilderFactory.createBuilder(id, StartEventBuilder.class, this, logicFlowDefinition);
//        return createBuilder(id, StartEventBuilder.class);
    }

    public AbstractLogicFlowBuilder sequenceFlow(){
        return sequenceFlow(null);
    }

    public AbstractLogicFlowBuilder sequenceFlow(String id){
        return logicFlowBuilderFactory.createBuilder(id, SequenceFlowBuilder.class, this, logicFlowDefinition);
//        return createBuilder(id, SequenceFlowBuilder.class);
    }

    public IfElseControlBuilder ifElseControl(){
        return ifElseControl(null);
    }

    public IfElseControlBuilder ifElseControl(String id) {
        return logicFlowBuilderFactory.createBuilder(id, IfElseControlBuilder.class, this, logicFlowDefinition);
//        return createBuilder(id, IfElseControlBuilder.class);
    }


    public <E extends AbstractLogicFlowBuilder>E customEvent(Class<E> abstractLogicFlowBuilderClass){
        return customEvent(abstractLogicFlowBuilderClass, null);
    }

    public <E extends AbstractLogicFlowBuilder>E customEvent(Class<E> abstractLogicFlowBuilderClass, String id){
//        return createBuilder(id, abstractLogicFlowBuilderClass);
        return logicFlowBuilderFactory.createBuilder(id, abstractLogicFlowBuilderClass, this, logicFlowDefinition);
    }

    public JavaClassTaskBuilder javaClassTask(){
        return javaClassTask(null);
    }

    public JavaClassTaskBuilder javaClassTask(String id) {
        return logicFlowBuilderFactory.createBuilder(id, JavaClassTaskBuilder.class, this, logicFlowDefinition);
//        return createBuilder(id, JavaClassTaskBuilder.class);
    }

//    private <T extends AbstractLogicFlowBuilder>T createBuilder(String id, Class<T> abstractLogicFlowBuilderClass){
//        logicFlowBuilderFactory.createBuilder(id, abstractLogicFlowBuilderClass, this, logicFlowDefinition);
//
//
//        //初始化当前构建器
//        T abstractLogicFlowBuilder = logicFlowConfiguration.getLogicFlowBuilderFactory()
//                .startCreateBuilder(id, abstractLogicFlowBuilderClass, this, logicFlowDefinition);
//
//        //控制器逻辑处理
//        parseControl(abstractLogicFlowBuilder);
//
//        logicFlowConfiguration.getLogicFlowBuilderFactory().addDefinitionsElement(abstractLogicFlowBuilder);
//        return abstractLogicFlowBuilder;
//    }
//
//
//    private void parseControl(AbstractLogicFlowBuilder currentAbstractLogicFlowBuilder){
//        //判断上一个构建器是否网关，是就设置给当前构建器
//        if(this instanceof IfElseControlBuilder){
//            currentAbstractLogicFlowBuilder.setCurrentGatewayAbstractLogicFlowBuilder((IfElseControlBuilder) this);
//        }else{
//            currentAbstractLogicFlowBuilder.setCurrentGatewayAbstractLogicFlowBuilder(this.getCurrentGatewayAbstractLogicFlowBuilder());
//        }
//    }




    protected void postCreateBuilder(E element, AbstractLogicFlowBuilder abstractLogicFlowBuilder){

    }

    public EndEventBuilder endEvent(){
        return endEvent(null);
    }

    public EndEventBuilder endEvent(String id) {
        return logicFlowBuilderFactory.createBuilder(id, EndEventBuilder.class, this, logicFlowDefinition);
//        return createBuilder(id, EndEventBuilder.class);
    }

    public LogicFlowDefinition done() {
        return this.logicFlowDefinition;
    }


    public String getId() {
        return id;
    }

    public T id(String id) {
        this.id = id;

        getElement().setResourceId(id);
        return (T) this;
    }

    public String getName() {
        return name;
    }

    public T name(String name) {
        this.name = name;

        getElement().setName(name);
        return (T) this;
    }

    public LogicFlowDefinition getLogicFlowDefinition() {
        return logicFlowDefinition;
    }

    public E getElement() {
        if(getElementClass() != LogicFlowDefinition.class){
            return element;
        }else{
            return (E) logicFlowDefinition;
        }
    }

    public void setElement(E element) {
        this.element = element;
    }

    public void setPrevAbstractLogicFlowBuilder(AbstractLogicFlowBuilder prevAbstractLogicFlowBuilder) {
        this.prevAbstractLogicFlowBuilder = prevAbstractLogicFlowBuilder;
    }

    public AbstractLogicFlowBuilder getPrevAbstractLogicFlowBuilder() {
        return prevAbstractLogicFlowBuilder;
    }

    public Map<String, SequenceFlow> getSequenceFlowElements() {
        return sequenceFlowElements;
    }

    public void setSequenceFlowElements(Map<String, SequenceFlow> sequenceFlowElements) {
        this.sequenceFlowElements = sequenceFlowElements;
    }

    protected abstract Class<E> getElementClass();

    public LogicFlowConfiguration getLogicFlowConfiguration() {
        return logicFlowConfiguration;
    }

    public void build(){

    }

    public IfElseControlBuilder getCurrentGatewayAbstractLogicFlowBuilder() {
        return currentGatewayAbstractLogicFlowBuilder;
    }

    public void setCurrentGatewayAbstractLogicFlowBuilder(IfElseControlBuilder currentGatewayAbstractLogicFlowBuilder) {
        this.currentGatewayAbstractLogicFlowBuilder = currentGatewayAbstractLogicFlowBuilder;
    }
}
